package org.xi2p;

import java.util.ArrayList;

public class Judgeline {
    // 扩展指数，粗暴地解决了边界外note显示不全的问题
    private static final double EXPAND_INDICATOR = 1;

    public double x = 0;
    public double y = 0;
    public double angle = 0;
    public double alpha = 0;

    public double[] point1;
    public double[] point2;

    public AlterObject xObject = new AlterObject();
    public AlterObject yObject = new AlterObject();
    public AlterObject alphaObject = new AlterObject();
    public AlterObject angleObject = new AlterObject();
    public AlterObject noteYObject = new NoteYObject();

    public ArrayList<Note> holds = new ArrayList<>();
    public ArrayList<Note> notHolds = new ArrayList<>();
    public ArrayList<Note> above1 = new ArrayList<>();
    public ArrayList<Note> above2 = new ArrayList<>();

    ArrayList<Note> visibleNotes = new ArrayList<>();

    Judgeline(){

    }

    public void update(double beat){
        // 更新判定线本身与note的数值，并刷新visibleNotes

        visibleNotes.clear();

        x = xObject.getValue(beat);
        y = yObject.getValue(beat);
        angle = angleObject.getValue(beat);
        alpha = alphaObject.getValue(beat);

        point1 = null;
        point2 = null;
        double[][] points = getPoints();

        if (points.length != 0 && alpha > 0){
            if (alpha > 255) {
                alpha = 255;
            }

            point1 = points[0];
            point2 = points[1];

        }

        for (Note note : above1){
            // 更新note数值并将合适的note加入列表
            note.upgrade(beat);
            if (
                    note.xInSurface < core.WIDTH * (1 + EXPAND_INDICATOR) &&
                    note.xInSurface > -core.WIDTH * EXPAND_INDICATOR &&
                    note.yInSurface > - core.HEIGHT * EXPAND_INDICATOR &&
                    note.yInSurface < core.HEIGHT * (1 + EXPAND_INDICATOR)){
                visibleNotes.add(note);
            }
        }

        for (Note note : above2){
            // 更新note数值并将合适的note加入列表
            note.upgrade(beat);
            if (
                    note.xInSurface < core.WIDTH * (1 + EXPAND_INDICATOR) &&
                            note.xInSurface > -core.WIDTH * EXPAND_INDICATOR &&
                            note.yInSurface > - core.HEIGHT * EXPAND_INDICATOR &&
                            note.yInSurface < core.HEIGHT * (1 + EXPAND_INDICATOR)){
                visibleNotes.add(note);
            }
        }
    }

//    public double[][] getPoints(){
//        ArrayList<double[]> _points = new ArrayList<>();
//        double _angle = angle % 180;
////        double _angle = angle - Math.floor(angle / 180) * 180;
//
//        double _tmp;
//
//        // 找出线段的左右边界
//        _tmp = core.LINE_LENGTH / 2 * Math.cos(
//                Math.toRadians(_angle)
//        );
//        double lineLeft = x + _tmp;
//        double lineRight = x - _tmp;
//
//        if (lineLeft > lineRight){
//            _tmp = lineRight;
//            lineRight = lineLeft;
//            lineLeft = _tmp;
//        }
//
//        // 找出线段的上下边界
//        _tmp = core.LINE_LENGTH / 2 * Math.sin(
//                Math.toRadians(_angle)
//        );
//        double lineTop = -y + _tmp;
//        double lineBottom = -y - _tmp;
//
//        if (lineTop < lineBottom){
//            _tmp = lineBottom;
//            lineBottom = lineTop;
//            lineTop = _tmp;
//        }
//
//        if (_angle % 90 == 0){
//            if (0 <= x && x <= core.WIDTH){
//                if (lineTop >= 0 && 0 >= lineBottom){
//                    _points.add(new double[]{x, 0});
//                }
//                if (lineTop >= -core.HEIGHT && -core.HEIGHT >= lineBottom){
//                    _points.add(new double[]{x, core.HEIGHT});
//                }
//            }
//
//        } else if (_angle % 180 == 0){
//            if (-core.HEIGHT <= -y && -y <= 0){
//                if (lineLeft <= 0 && 0 <= lineRight){
//                    _points.add(new double[]{0, y});
//                }
//                if (lineLeft <= core.WIDTH && core.WIDTH <= lineRight){
//                    _points.add(new double[]{core.WIDTH, y});
//                }
//            }
//        } else {
//            // 先求斜率和截距
//            double k = Math.tan(Math.toRadians(_angle));
//            double b = -y - x * k;
//
//            // 上方直线交点
//            double topCrossX = -b / k;
//
//            // 下方直线交点
//            // y = kx + b, y = HEIGHT => x = (-HEIGHT - b) / k
//            double bottomCrossX = (-core.HEIGHT - b) / k;
//
//            // 左侧直线交点
//            double rightCrossY = core.WIDTH * k + b;
//
//            // 右侧直线交点
//            // left_cross_y = b
//
//            if (0 <= topCrossX && topCrossX <= core.WIDTH &&
//                    lineTop >= 0 && 0 >= lineBottom){
//                _points.add(new double[]{topCrossX, 0});
//            }
//            if (0 <= bottomCrossX && bottomCrossX <= core.WIDTH &&
//                    lineTop >= -core.HEIGHT && -core.HEIGHT >= lineBottom){
//                _points.add(new double[]{bottomCrossX, core.HEIGHT});
//            }
//            // left_cross_y = b
//            if (-core.HEIGHT < b && b < 0 &&
//                    lineLeft <= 0 && 0 <= lineRight){
//                _points.add(new double[]{0, -b});
//            }
//            if (-core.HEIGHT < rightCrossY && rightCrossY < 0 &&
//                    lineLeft <= core.WIDTH && core.WIDTH <= lineRight){
//                _points.add(new double[]{core.WIDTH, -rightCrossY});
//            }
//        }
//
//        if (_points.size() == 1){
//            // 只有一个交点，那么可能是线不够长
//
//            if (-core.HEIGHT <= lineTop && lineTop <= 0){
//                // 上方端点在画面内
//                double pointX = _angle > 90 ? lineLeft : lineRight;
//                if (0<= pointX && pointX <= core.WIDTH){
//                    _points.add(new double[]{pointX, -lineTop});
//                }
//            } else if (-core.HEIGHT <= lineBottom && lineBottom <= 0) {
//                // 下方端点在画面内
//                double pointX = _angle > 90 ? lineRight : lineLeft;
//                if (0 <= pointX && pointX <= core.WIDTH){
//                    _points.add(new double[]{pointX, -lineBottom});
//                }
//            } else {
//                _points.clear();
//            }
//
//        }
//
//        if (_points.size() == 0){
//            return new double[][]{};
//        } else {
//            return new double[][]{
//                    _points.get(0),
//                    _points.get(1)
//            };
//        }
//    }
    public double[][] getPoints(){
        double _angleR = Math.toRadians(angle - Math.floor(angle / 180) * 180);
        double[][] points = new double[2][2];
        double x1 = x + (core.LINE_LENGTH / 2.0) * Math.cos(_angleR);
        double y1 = y - (core.LINE_LENGTH / 2.0) * Math.sin(_angleR);
        double x2 = x - (core.LINE_LENGTH / 2.0) * Math.cos(_angleR);
        double y2 = y + (core.LINE_LENGTH / 2.0) * Math.sin(_angleR);
        double [] p1 = new double[]{x1, y1};
        double [] p2 = new double[]{x2, y2};
        return new double[][]{p1, p2};
    }
}
